package server.controller.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.web.bind.annotation.*;
import plug.result.ReqPage;
import plug.result.RetResponse;
import plug.result.RetResult;
import server.dao.*;
import server.model.dto.OrderDto;
import server.model.entity.*;
import server.model.vo.OrderVo;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 创建人:    xvzhe
 * 创建时间:
 * 修改时间:
 * 版本:      v1.0
 */
@RestController
@RequestMapping("/v2/order")
@CrossOrigin(origins = "*")
@Api(value = "对外接口（订单）", tags = {"需登录(订单)"})
public class SoController {
    @Autowired
    private ShopCarDao shopCarDao;
    @Autowired
    private ShopOrderDao shopOrderDao;
    @Autowired
    private ShopOrderItemDao shopOrderItemDao;
    @Autowired
    private UserSiteDao userSiteDao;
    @Autowired
    UsersDao usersDao;
    @Autowired
    UserBlanceDao userBlanceDao;
    @Autowired
    FrmDictionDao frmDictionDao;
    @Autowired
    OrderSpackDao orderSpackDao;


    @ApiOperation("根据购物车生成订单")
    @PostMapping
    @Transactional
    public RetResult addOrder(@RequestBody OrderDto orderDto) {
        Users users = (Users) SecurityUtils.getSubject().getSession().getAttribute("Users");
        List<ShopCar> cars = shopCarDao.findByIdIn(orderDto.getCarId());
        ShopOrder shopOrder = new ShopOrder();
        shopOrder.setUsers(usersDao.findById(users.getId()).get());
        if (orderDto.getAnnul().compareTo(BigDecimal.ZERO) > 0) {
            UserBlance userBlance = userBlanceDao.findByTypeAndUserId(UserBlance.Type.RMB, users.getId());
            if (userBlance.getMoney().subtract(orderDto.getAnnul()).compareTo(BigDecimal.ZERO) < 0) {
                return RetResponse.makeErrRsp("余额不足");
            }
            userBlance.setFrostMoney(userBlance.getFrostMoney().add(orderDto.getAnnul()));
            userBlance.setMoney(userBlance.getMoney().subtract(orderDto.getAnnul()));
            userBlanceDao.save(userBlance);
        }

        shopOrder.setAnnul(orderDto.getAnnul());
        shopOrder.setStatus(ShopOrder.Status.NO_G);
        shopOrder.setCount(cars.stream().mapToInt(ShopCar::getCount).sum());
        if (shopOrder.getCount() == 0 || shopOrder.getUsers() == null) {
            return RetResponse.makeErrRsp("生成订单失败！");
        }
        AtomicReference<BigDecimal> money = new AtomicReference<BigDecimal>(BigDecimal.ZERO);
        cars.stream().forEach(item -> {
            money.getAndSet(new BigDecimal(item.getCount()).multiply(item.getShop().getMoney()));
        });
        shopOrder.setIncomeMoney(money.get());
        shopOrder.setMoney(money.get());
        if (orderDto.getAnnul().compareTo(money.get()) > 0) {
            return RetResponse.makeErrRsp("抵扣金额不能大于订单总额！");
        }
        if (orderDto.getIsDefault()) {
            shopOrder.setUserSite(userSiteDao.findByUserIdAndIsDefaultAndStatus(users.getId(), true, true));
        } else if (StringUtils.isNotBlank(orderDto.getSiteId()) && userSiteDao.findById(orderDto.getSiteId()).isPresent()) {
            shopOrder.setUserSite(userSiteDao.findById(orderDto.getSiteId()).get());
        } else {
            return RetResponse.makeErrRsp("请选择收货地址！");
        }
        if (shopOrder.getUserSite() == null) {
            return RetResponse.makeErrRsp("默认收货地址为空！");
        }
        shopOrder = shopOrderDao.save(shopOrder);
        ShopOrder finalShopOrder = shopOrder;
        cars.stream().forEach(item -> {
            ShopOrderItem shopOrderItem = new ShopOrderItem();
            shopOrderItem.setCount(item.getCount());
            shopOrderItem.setMoney(new BigDecimal(item.getCount()).multiply(item.getShop().getMoney()));
            shopOrderItem.setShop(item.getShop());
            shopOrderItem.setShopOrder(finalShopOrder);
            shopOrderItemDao.save(shopOrderItem);
        });
        shopCarDao.deleteByIdIn(orderDto.getCarId());
        return RetResponse.makeOKRsp(shopOrder);
    }

    @ApiOperation("我的订单")
    @PostMapping("/all")
    public RetResult all(@RequestBody ReqPage reqPage) {
        Users users = (Users) SecurityUtils.getSubject().getSession().getAttribute("Users");
        JSONObject req = Optional.ofNullable(reqPage.getCommon()).orElseGet(JSONObject::new);
        ShopOrder entity = JSON.parseObject(req.toJSONString(), ShopOrder.class);
        entity.setUsers(usersDao.findById(users.getId()).get());
        int page = reqPage.getPage() - 1;
        int size = reqPage.getLimit();
        Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "modifiedTime");
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("users.name", ExampleMatcher.GenericPropertyMatchers.contains());
        Example<ShopOrder> example = Example.of(entity, matcher);
        Page<ShopOrder> pages = shopOrderDao.findAll(example, pageable);
        List<ShopOrder> pageList = pages.getContent();
        List<OrderVo> orderVos = new LinkedList<>();
        pageList.stream().forEach(item -> {
            OrderVo orderVo = new OrderVo();
            orderVo.setShopOrder(item);
            orderVo.setShopOrderItems(shopOrderItemDao.findByShopOrderId(item.getId()));
            orderVos.add(orderVo);
        });
        return RetResponse.makeRsp(0, "成功", orderVos, (int) pages.getTotalElements());
    }

    @ApiOperation("减免")
    @PostMapping("/{orderId}/annul")
    public RetResult annul(@PathVariable String orderId,@RequestParam BigDecimal annul) {
        Users users = (Users) SecurityUtils.getSubject().getSession().getAttribute("Users");
        Optional<ShopOrder> order = shopOrderDao.findById(orderId);
        if(order.get().getUsers().getId().equals(users.getId())){
            if (annul.compareTo(BigDecimal.ZERO) > 0) {
                UserBlance userBlance = userBlanceDao.findByTypeAndUserId(UserBlance.Type.RMB, users.getId());
                if (userBlance.getMoney().subtract(annul).compareTo(BigDecimal.ZERO) < 0) {
                    return RetResponse.makeErrRsp("余额不足");
                }
                userBlance.setFrostMoney(userBlance.getFrostMoney().add(annul));
                userBlance.setMoney(userBlance.getMoney().subtract(annul));
                userBlanceDao.save(userBlance);
                order.get().setAnnul(annul);
                shopOrderDao.save(order.get());
                return RetResponse.makeOKRsp();
            }
            return RetResponse.makeErrRsp("请输入扣减金额");
        }else{
            return RetResponse.makeErrRsp("这不是你的订单");
        }
    }

    @ApiOperation("取消订单")
    @PutMapping("/status/{id}")
    public RetResult putStatus(@PathVariable String id) {
        ShopOrder shopOrder = shopOrderDao.findById(id).get();
        if (shopOrder.getStatus().getNumber() > 1) {
            return RetResponse.makeErrRsp("已付款不允许取消！");
        }
        shopOrder.setStatus(ShopOrder.Status.CALL);
        shopOrderDao.save(shopOrder);
        UserBlance ub = userBlanceDao.findByTypeAndUserId(UserBlance.Type.RMB, shopOrder.getUsers().getId());
        ub.setFrostMoney(ub.getFrostMoney().subtract(shopOrder.getAnnul()));
        ub.setMoney(ub.getMoney().add(shopOrder.getAnnul()));
        userBlanceDao.save(ub);
        return RetResponse.makeOKRsp();
    }

    @ApiOperation("订单收货")
    @PutMapping("/end/{id}")
    public RetResult putEnd(@PathVariable String id) {
        ShopOrder shopOrder = shopOrderDao.findById(id).get();
        if (shopOrder.getStatus().getNumber() != 3) {
            return RetResponse.makeErrRsp("订单未发货！");
        }
        shopOrder.setStatus(ShopOrder.Status.END);
        shopOrderDao.save(shopOrder);
        return RetResponse.makeOKRsp();
    }

    @ApiOperation("获得支付方式")
    @PostMapping("/pay")
    public RetResult message() {
        Random rand = new Random();
        List<String> ls = frmDictionDao.findByTypeOrderByKeyst("PAY")
                .stream().map(FrmDiction::getVal).collect(Collectors.toList());
        return RetResponse.makeOKRsp(ls.get(rand.nextInt(ls.size())));
    }

    @ApiOperation("完成付款")
    @PostMapping("/pay/over/{orderId}")
    public RetResult over(@PathVariable String orderId) {
        OrderSpack orderSpack = new OrderSpack();
        Users users = (Users) SecurityUtils.getSubject().getSession().getAttribute("Users");
        orderSpack.setStatus(false);
        orderSpack.setUsers(usersDao.findById(users.getId()).get());
        orderSpack.setShopOrder(shopOrderDao.findById(orderId).get());
        ShopOrder sp = shopOrderDao.findById(orderId).get();
        sp.setStatus(ShopOrder.Status.NO);
        try {
            orderSpackDao.save(orderSpack);
        } catch (Exception e) {
            return RetResponse.makeErrRsp("你已经点击过了！");
        }
        return RetResponse.makeOKRsp();
    }
}
